package com.zdb.java.lang;

import org.junit.Test;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class StringTest {

    @Test
    public void testSplit() {

        String ss = ",aa,bb,cc,dd,,,";
        String[] array = ss.split(",");
        //结果是5，而不是预想中的8
        System.out.println(array.length);
        for (int i = 0; i < array.length; i++) {
            System.out.println("[" + array[i] + "]");
        }
        System.out.println("---------------");

        array = ss.split(",", -1);
        //结果是5，而不是预想中的8
        System.out.println(array.length);
        for (int i = 0; i < array.length; i++) {
            System.out.println("[" + array[i] + "]");
        }
        System.out.println("---------------");

    }

    @Test
    public void testSplit2() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            sb.append("adsfasdjf;ajsdf;kaj;sdkfj;aksjdf;kajsd;fja;skdjf;aksjd;fkasd;fkas;dkfa;sdkfj;aksdf;kasd;fka;sdkfj;aksdjf;akjsd;fkajsd;kfja;sdkfj;aksdjf;kajsdfkja;sdkfja;ksdjf;aksjdf;kajsd;fkja;sdkfj;aksdjf;aksd;fkajs;dfka;sdkfj;aksdjf;aksdjf;aksdjf;kasjdf;kajsd;fkjas;dkfj;adsk");
        }
        int i = sb.toString().split("_").length;
        System.out.println(i);
    }

    /**
     * -XX:StringTableSize=1009 控制存储字符常量的hash表的大小，尽量设置大一点，小了会导致hash碰撞消耗CPU
     * -XX:+PrintGCDetails -XX:MetaspaceSize=3m -XX:MaxMetaspaceSize=30m
     */
    @Test
    public void testGC() throws Exception {
        String str = null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1024*50; i++) {
            sb.append("a");
        }
        String pre = sb.toString().intern();
        str = (pre + 0).intern();
        System.out.println("\n");
        System.out.println("--内存地址1：" + System.identityHashCode(str));
        for (int i = 0; i < 1000; i++) {
            str = (pre + i).intern();
//            str = (pre + i);
            System.out.println("------" + i);
//            System.gc();
            Thread.sleep(1);
        }
        str = (pre + 0).intern();
        System.out.println("--内存地址2：" + System.identityHashCode(str));
    }

    /**
     * 判断字符串常量池里的内存分配??，1. 在metaspace; 2,堆里
     *
     * 答案： 字符串常量池的对象是建立在堆里，常量池里持有它的引用。
     * 因为下面的例子，将String.intern()后的对象放到list中，
     * 最后报java.lang.OutOfMemoryError: GC overhead limit exceeded异常，
     * 说明大量堆内存被占用,gcdetails:
     * [Full GC (Ergonomics) [PSYoungGen: 5631K->5575K(6144K)] [ParOldGen: 13704K->13704K(13824K)] 19336K->19280K(19968K), [Metaspace: 5194K->5194K(1056768K)], 0.0752724 secs] [Times: user=0.27 sys=0.00, real=0.08 secs]
     * [Full GC (Ergonomics) [PSYoungGen: 5631K->5577K(6144K)] [ParOldGen: 13704K->13704K(13824K)] 19336K->19282K(19968K), [Metaspace: 5194K->5194K(1056768K)], 0.0789650 secs] [Times: user=0.30 sys=0.00, real=0.08 secs]
     * [Full GC (Ergonomics) [PSYoungGen: 5632K->5579K(6144K)] [ParOldGen: 13704K->13704K(13824K)] 19336K->19284K(19968K), [Metaspace: 5194K->5194K(1056768K)], 0.0777745 secs] [Times: user=0.28 sys=0.00, real=0.07 secs]
     * 老年代的内存回收不了，说明该内存对象都被放到了堆里
     * @throws Exception
     */
    @Test
    public void testMetaspaceGC() throws Exception {
        String str = "";

        StringBuilder sb =  new StringBuilder();
        for (int i = 0; i < 100; i++) {
            sb.append('a');
        }
        String pre = sb.toString().intern();

        str = (pre + 0).intern();
        System.out.println("\n");
        System.out.println(System.identityHashCode(str));

        List<String> list = new LinkedList<>();
        for (int i = 0; i < 10000000; i++) {
            // 将字符串放到常量池中，如果最后报的是内存溢出，说明是放在了堆里
            // -ea -XX:MetaspaceSize=3m -XX:MaxMetaspaceSize=20m -XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:+PrintGCTimeStamps
            str = (pre + "i").intern();
            list.add(str);
        }
        str = (pre + 0).intern();
        System.out.println(System.identityHashCode(str));

    }
    @Test
    public void testMetaspaceGCGenCode() throws Exception {
        String str = null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1024*50; i++) {
            sb.append("a");
        }
        String pre = sb.toString();

        File file = new File("dir/code.txt");
        if(file.exists()) {
            file.delete();
        }

        BufferedWriter bw = new BufferedWriter(new FileWriter(file));

        for (int i = 0; i < 1000; i++) {

            bw.write("str = \"" + pre + i + "\";");
            bw.newLine();
            if(i % 100 == 0) {
                bw.flush();
            }
        }
        bw.flush();
        bw.close();
    }
}
